﻿using BCCommon;
using BCCommon.Enums;
using BCData.SystemExceptionRecord;
using BCDto.WebSocketComponent;
using BCEntity.SystemExceptionRecordEntity;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace BCWebSocket
{
    /// <summary>
    /// WebSocket工厂
    /// </summary>
    public class WebSocketFactory : IWebSocketFactory
    {
        private const int BufferSize = 4096;
        private readonly string WebSocketBusinessServiceName = "BCWebSocket.{0}.{0}Service,BCWebSocket";
        private readonly ISystemExceptionRecordData systemExceptionRecordData;
        
        public WebSocketFactory(ISystemExceptionRecordData systemExceptionRecordData)
        {
            this.systemExceptionRecordData = systemExceptionRecordData;
        }
        /// <summary>
        /// 接待用户下线
        /// </summary>
        /// <param name="concurrentDictionary">在线沟通字典</param>
        /// <param name="receptionUser">接待用户</param>
        public void Offline(ConcurrentDictionary<string, WebSocketUserDto> concurrentDictionary, string receptionUser)
        {
            Type type = Type.GetType(string.Format(WebSocketBusinessServiceName, ChatType.Custom.ToString()));
            IWebSocketBusinessService businessService = this.GetBusinessService(type);
            businessService.Offline(concurrentDictionary, receptionUser);
        }

        /// <summary>
        /// 内容处理
        /// </summary>
        /// <param name="requestContent">请求内容</param>
        /// <returns></returns>
        public WebSocketResponseDto ContentHandle(WebSocketRequestDto requestContent)
        {
            Type type = Type.GetType(string.Format(WebSocketBusinessServiceName, requestContent.ChatType.ToString()));
            IWebSocketBusinessService businessService = this.GetBusinessService(type);
            return businessService.ContentHandle(requestContent);
        }
        /// <summary>
        /// 操作处理
        /// </summary>
        /// <param name="requestContent">请求内容</param>
        /// <returns></returns>
        public WebSocketResponseDto OperationHandle(WebSocketRequestDto requestContent)
        {
            Type type = Type.GetType(string.Format(WebSocketBusinessServiceName, requestContent.ChatType.ToString()));
            IWebSocketBusinessService businessService = this.GetBusinessService(type);
            return businessService.OperationHandle(requestContent);
        }
        /// <summary>
        /// 重新分配客服
        /// </summary>
        /// <param name="concurrentDictionary">在线沟通字典</param>
        /// <param name="adminId">管理员Id</param>
        public void RedistributeCustom(ConcurrentDictionary<string, WebSocketUserDto> concurrentDictionary,string adminId)
        {
            Type type = Type.GetType(string.Format(WebSocketBusinessServiceName, ChatType.Custom.ToString()));
            IWebSocketBusinessService businessService = this.GetBusinessService(type);
            businessService.RedistributeCustom(concurrentDictionary, adminId);
        }

        /// <summary>
        /// 精确的回应
        /// </summary>
        /// <param name="webSocket">webSocket对象</param>
        /// <param name="responseContent">回应内容</param>
        /// <returns></returns>
        private async Task AccurateResponse(WebSocket webSocket, string responseContent)
        {
            if (webSocket.State == WebSocketState.Open)
            {
                var buffer = new byte[BufferSize];
                byte[] backInfo = UTF8Encoding.Default.GetBytes(responseContent);
                var outgoing = new ArraySegment<byte>(backInfo, 0, backInfo.Length);
                await webSocket.SendAsync(outgoing, WebSocketMessageType.Text, true, CancellationToken.None);
            }
        }

        /// <summary>
        /// 获取业务服务接口实例
        /// </summary>
        /// <param name="type">业务类型对象</param>
        /// <returns></returns>
        private IWebSocketBusinessService GetBusinessService(Type type)
        {
            if (type == null || !type.GetTypeInfo().ImplementedInterfaces.Contains(typeof(IWebSocketBusinessService)))
            {
                throw new NotImplementedException("WebSocket沟通服务未实现");
            }
            IWebSocketBusinessService webSocketBusinessService = null;
            foreach (var constructor in type.GetTypeInfo().GetConstructors())
            {
                IEnumerable<object> parameters = constructor.GetParameters().Select(p => GeneralContainer.ServiceProvider.GetService(p.ParameterType));

                try
                {
                    webSocketBusinessService = constructor.Invoke(parameters.ToArray()) as IWebSocketBusinessService;
                }
                catch (Exception ex)
                {
                    Task.Run(delegate
                    {
                        this.systemExceptionRecordData.Create(new SystemExceptionRecordEntity
                        {
                            Name = ex.GetType().Name,
                            HelpLink = ex.HelpLink,
                            Message = ex.Message,
                            StackTrace = ex.StackTrace,
                            HResult = ex.HResult,
                            Data = JObject.FromObject(ex.Data).ToString(),
                            Source = ex.Source ?? string.Empty,
                            InnerException = ex.InnerException?.GetType()?.Name ?? string.Empty,
                            CreateTime = DateTime.Now
                        });
                    });
                }
            }
            return webSocketBusinessService;
        }
    }
}
